package com.migu.rbac.config;

import com.migu.rbac.RbacConstant;
import com.migu.rbac.domain.User;
import com.migu.rbac.remote.ValidateTokenRestTemplate;
import com.migu.rbac.util.Constant;
import com.migu.rbac.util.Response;
import com.migu.rbac.util.TokenProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


public class JWTAuthorizeFilter extends OncePerRequestFilter {

    @Value("${security.jwt.header}")
    private String AUTHORIZATION_HEADER;
    @Value("${security.jwt.bearer-header}")
    private String BEARER_HEADER;

    @Autowired
    private ValidateTokenRestTemplate validateTokenRestTemplate;

    @Value("${remote.portalsso.basePath:default}")
    private String url;
    @Value("${remote.portalsso.appId:default}")
    private String appId;

    @Autowired
    private TokenProvider tokenProvider;

    private Logger log = LoggerFactory.getLogger(TokenProvider.class);

    /**
     * 过滤器, 验证Token, 设置权限
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String userStr = request.getHeader(RbacConstant.Common.SSO_USER);
        String authorization = request.getHeader(AUTHORIZATION_HEADER);
        logger.info("authorization:" + authorization);
        if (!StringUtils.isEmpty(userStr)) {
            this.doFilterInternalNomsWeb(userStr, request, response, filterChain);
        } else if (!StringUtils.isEmpty(authorization)) {
            this.doFilterInternalAppManagementJwt(request, response, filterChain);
        } else {
            //response.addHeader("code", Constant.NO_TOKEN);
            //response.sendError(Constant.VALIDATE_CODE, Constant.VALIDATE_NO_TOKEN_DESC);
            filterChain.doFilter(request, response);
        }
    }

    /**
     * 乐高登录, 校验乐高的Token
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws ServletException
     * @throws IOException
     */
    private void doFilterInternalNomsWeb(String userStr, HttpServletRequest request, HttpServletResponse response,
                                         FilterChain filterChain) throws ServletException, IOException {

        User user = tokenProvider.getUserInfo(userStr);
        if (null == user) {
            response.addHeader("code", Constant.VALIDATE_FAIL);
            response.sendError(Constant.VALIDATE_CODE, Constant.VALIDATE_FAIL_DESC);
            return;
        }
        // 调用乐高鉴权接口, 检验Token
        Response res = validateTokenRestTemplate.validateToken(String.format(url, user.getNewtoken(), appId));
        if (res.getIsSuccess()) {
            //获取用户权限
            Authentication authentication = this.tokenProvider.getAuthentivationByNoms(user);
            //将用户权限设置到SecurityContext中
            SecurityContextHolder.getContext().setAuthentication(authentication);

            filterChain.doFilter(request, response);
        } else if (Constant.MODULE_CODE_NOT_PERMIT.equals(res.getErrorCode())) {
            response.addHeader("redirectUrl", res.getRedirectUrl());
            response.addHeader("code", Constant.NO_AUTHORITY);
            response.sendError(Constant.VALIDATE_CODE, Constant.VALIDATE_NO_AUTHORITY_DESC);
        } else {
            response.addHeader("code", Constant.VALIDATE_FAIL);
            response.sendError(Constant.VALIDATE_CODE, Constant.VALIDATE_FAIL_DESC);
        }
    }

    /**
     * 非乐高登录, 自行校验Token
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws ServletException
     * @throws IOException
     */
    private void doFilterInternalAppManagementJwt(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws
            ServletException, IOException {
        //解析出JWT
        String jwt = resolveToken(request);
        logger.info("jwt:........." + jwt);
        if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
            log.info("has-jwt:" + jwt);
            //通过JWT获取用户的权限
            Authentication authentication = this.tokenProvider.getAuthentication(jwt);
            //将用户权限设置到SecurityContext中
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        filterChain.doFilter(request, response);
    }

    private String resolveToken(HttpServletRequest request) {
        //从HTTP头的Authorization中解析出JWT
        String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(BEARER_HEADER)) {
            //解析“Bearer ”之后的字符串
            return bearerToken.substring(7, bearerToken.length());
        }
        //从浏览器的cookie中获取Authorization字段
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(AUTHORIZATION_HEADER)) {
                    return cookie.getValue();
                }
            }
        }
        return null;

    }

}
